package com.darwin.darwinImage.dar
{
	import com.darwin.darwinImage.jpg.JPEG32;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	/**
	 * Dar文件编码器
	 * @author Roland
	 */
	public class DarEncoder
	{
		public function DarEncoder()
		{
		}
		
		/**
		 * 将传入dar格式数组编码为*.dar文件二进制数据
		 * @param sourceArr *.dar源数据 结构 [{materialName:"",UP:displayObject
		 * 								   MID:displayObject,DOWN:displayObject},{}]
		 * @return 
		 * 
		 */		
		public function encode(sourceArr:Array):ByteArray
		{
			var returnByteArray:ByteArray = new ByteArray();
			var returnObj:Object = new Object();
			for(var i:int = 0;i<sourceArr.length;i++)
			{
				var obj:Object = sourceArr[i];
				returnObj[obj["materialName"]] = getDarwinBitmapDataObj(obj);
			}
			returnByteArray.writeUnsignedInt(5);	
			returnByteArray.writeObject(returnObj);
			returnByteArray.compress();
			returnByteArray.position = 0;
			return returnByteArray;
		}
		
		private function getDarwinBitmapDataObj(obj:Object):Object
		{
			var returnDarwinBitmapDataObj:Object = new Object();
			
			if(obj.hasOwnProperty("UP"))
			{
				returnDarwinBitmapDataObj["UP"] = parseDarwinDisplayObject(obj["UP"]);
			}
			
			if(obj.hasOwnProperty("MID"))
			{
				returnDarwinBitmapDataObj["MID"] = parseDarwinDisplayObject(obj["MID"]); 
			}
			
			if(obj.hasOwnProperty("DOWN"))
			{
				returnDarwinBitmapDataObj["DOWN"] = parseDarwinDisplayObject(obj["DOWN"]);
			}
			
			return returnDarwinBitmapDataObj;
		}
		
		/**
		 * 将动画转换为DarwinBitmapData中一条动画数据 
		 * @param displayObject
		 * @return 
		 * 
		 */		
		private function parseDarwinDisplayObject(displayObject:DisplayObject):Object
		{
			var returnObj:Object = new Object();
			// 动画整体偏移量 [offSetX,offSetY]
			var offSet:Array = [];
			//动画最大宽高 [maxW,maxH]
			var maxRect:Array = [];
			//位图数据
			var bitmapDataByteArray:ByteArray = new ByteArray();
			//播放信息 [[offX,offY,w,h,targetX,targetY,clearTag],[]]
			// offX offY w h 该帧矩形 targetX,targetY 目标位置  clearTag是否清除上一张位图信息 gotoFrame跳转到第几帧 loop 循环跳转的次数
			var frameMes:Array = [];
			var bitmapRect:Array = [];
			
			var offSetX:Number = 0;
			var offSetY:Number = 0;
			var bottom:Number = 0;
			var right:Number = 0;
			var maxW:Number = 0;
			var maxH:Number = 0;
			var rect:Rectangle;
			
			// 用于获取循环播放信息
			var getFrameMesFunc:Function;
			var frameLoopMes:Array = [];
			
			if(displayObject)
			{
				getFrameMesFunc = displayObject["getFrameMes"]; 
				if(getFrameMesFunc != null)
				{
					frameLoopMes = getFrameMesFunc();
				}
			}
			
			var tmpMC:MovieClip;
			
			if(displayObject is MovieClip)
			{
				tmpMC = MovieClip(displayObject);
				for(var m:uint = 1; m<=tmpMC.totalFrames; m++)
				{
					tmpMC.gotoAndStop(m);
					rect = tmpMC.getBounds(tmpMC);
					
					if(rect.top < 0 && rect.top < offSetY) offSetY = rect.top;
					if(rect.left < 0 && rect.left < offSetX) offSetX = rect.left;
					if(rect.bottom > 0 && rect.bottom > bottom)bottom = rect.bottom;
					if(rect.right > 0 && rect.right > right)right = rect.right;
				}
				tmpMC.gotoAndStop(1);
			}else if(displayObject is Sprite)
			{
				rect = displayObject.getBounds(displayObject);
				offSetX = rect.left;
				offSetY = rect.top;
				bottom = rect.bottom;
				right = rect.right;
			}
			
			//得到整体位图偏移量 和最大宽高
			maxH = bottom - offSetY;
			maxW = right - offSetX;
			offSet = [offSetX,offSetY];
			maxRect = [maxW,maxH];
			
			//处理位图信息
			var bitmapDataList:Array = [];
			var container:Sprite = new Sprite();
			
			if(tmpMC)
			{
				for(var n:uint = 1;n<=tmpMC.totalFrames; n++)
				{
					while(container.numChildren)
					{
						container.removeChildAt(0);
					}
					tmpMC.gotoAndStop(n);
					tmpMC.x = - offSetX;
					tmpMC.y = - offSetY;
					container.addChild(tmpMC);
					var bdRect:Rectangle = container.getBounds(container);
					
					var bitmapData:BitmapData = new BitmapData(bdRect.right > 0 ? bdRect.right : 1,bdRect.bottom > 0 ? bdRect.bottom : 1,true,0);
					bitmapData.draw(container);
					bitmapDataList.push(bitmapData);
					//测试代码
					//					var bitmap:Bitmap = new Bitmap(bitmapData);
					//					bitmap.scaleX = bitmap.scaleY = .5;
					//					bitmap.x = 10 + n*bitmap.width;
					//					bitmap.y = 100;
					//					App.appStage.addChild(bitmap);
				}
			}else
			{
				container.addChild(displayObject);
				displayObject.x = - offSetX;
				displayObject.y = - offSetY;
				var disBitmapData:BitmapData = new BitmapData(displayObject.width > 0 ? displayObject.width : 1,displayObject.height > 0 ? displayObject.height : 1,true,0);
				disBitmapData.draw(container);
				bitmapDataList.push(disBitmapData);
			}
			
			var endBitmapDataObj:Object = formatEndBitmapData(bitmapDataList);
			var endBitmapData:BitmapData = endBitmapDataObj["endBimapData"] as BitmapData;
			
			var jpeg32:JPEG32 = new JPEG32();
			bitmapDataByteArray =  jpeg32.encode(endBitmapData);
			bitmapDataByteArray.position = 0;
			
			
			returnObj["offSet"] = offSet;
			returnObj["maxRect"] = maxRect;
			returnObj["bitmapDataByteArray"] = bitmapDataByteArray;
			var tempFrameMes:Array = endBitmapDataObj["frameMes"];
			if(frameLoopMes.length != 0)
			{
				for(var loop:int = 0; loop<frameLoopMes.length; loop++)
				{
					var loopObj:Object = frameLoopMes[loop];
					var frameIndex:int = loopObj["frame"];
					tempFrameMes[frameIndex][7] = loopObj["goto"];
					tempFrameMes[frameIndex][8] = loopObj["loop"];
				}
			}
			returnObj["frameMes"] = tempFrameMes;
			
			returnObj["bitmapRect"] = [endBitmapData.width,endBitmapData.height];
			return returnObj;
		}
		
		private var _frameMesDic:Dictionary = new Dictionary();
		/**
		 * 将得到的位图序列数组 转换为最终需要的位图数据格式 
		 * @param bitmapDataList
		 * @return {endBimapData:bitmapData,frameMes:[]}
		 * 
		 */		
		private function formatEndBitmapData(bitmapDataList:Array):Object
		{
			var returnObj:Object = new Object();
			//总位图容器
			var totalContainer:Sprite = new Sprite();
			var frameMes:Array = [];
			//最终需要保存的位图信息
			var endBitmapDataList:Array = [];
			for(var i:int = 0; i<bitmapDataList.length; i++)
			{
				var tempBitmapData:BitmapData = bitmapDataList[i]; 
				if(!tempBitmapData){continue;}
				//当前帧位图在总位图上的开始位置
				var offX:Number = 0;
				var offY:Number = 0;
				//当前帧位图的宽高
				var w:Number = 0;
				var h:Number = 0;
				//该帧位图在最终动画上的位置
				var targetX:Number = 0;
				var targetY:Number = 0;
				//当前帧的显示是否需要清除上一帧位图 0为不需要清除上一帧位图  1为需要清除
				var clearTag:int;
				
				//当前帧是否需要直接跳转到某帧
				var gotoFrame:int = 0;
				//是否需要循环的次数
				var loop:int = 0;
				
				if(endBitmapDataList.length == 0)
				{
					endBitmapDataList.push(tempBitmapData);
					//将需要保存的位图 保存在 totalContainer容器内
					var bitmap1:Bitmap = new Bitmap(tempBitmapData);
					totalContainer.addChild(bitmap1);
					
					offX = offY = 0;
					w = tempBitmapData.width;
					h = tempBitmapData.height;
					targetX = 0;
					targetY = 0;
					frameMes = [[offX,offY,w,h,targetX,targetY,clearTag,gotoFrame,loop]];
					_frameMesDic[tempBitmapData] = [offX,offY,w,h,targetX,targetY,clearTag,gotoFrame,loop];
				}else
				{
					var prevBitmapData:BitmapData = bitmapDataList[i-1];
					if(!prevBitmapData){continue;}
					//得到前后两张位图对比结果
					var framMesDataObj:FrameMesDataObj = compareBitmapData(tempBitmapData,prevBitmapData);
					var resultBitmapData:BitmapData = framMesDataObj.bitmapData;
					
					var tempLen:int = endBitmapDataList.length;
					var count:int = 0;
					for(var n:int = 0; n<tempLen;n++)
					{
						var contrastsBitmapData:BitmapData = endBitmapDataList[n];
						//如果找到了相同位图
						if(resultBitmapData.compare(contrastsBitmapData) == 0)
						{
							//提取与此结果位图相同的位图 frameMes信息
							//							var tempArr:Array = frameMes[n];
							var tempArr:Array = _frameMesDic[contrastsBitmapData];
							offX = tempArr[0];
							offY = tempArr[1];
							w = resultBitmapData.width;
							h = resultBitmapData.height;
							targetX = framMesDataObj.targetX;
							targetY = framMesDataObj.targetY;
							clearTag = framMesDataObj.clearTag;
							frameMes.push([offX,offY,w,h,targetX,targetY,clearTag,gotoFrame,loop]);
							_frameMesDic[resultBitmapData] = [offX,offY,w,h,targetX,targetY,clearTag,gotoFrame,loop];
							break;
						}
						count ++;
					}
					// endBitmapDataList中未找到相同的位图
					if(count == tempLen)
					{
						endBitmapDataList.push(resultBitmapData);
						var bitmap2:Bitmap = new Bitmap(resultBitmapData);
						bitmap2.x = totalContainer.width;
						totalContainer.addChild(bitmap2);
						offX = bitmap2.x;
						frameMes.push([offX,offY,resultBitmapData.width,resultBitmapData.height
							,framMesDataObj.targetX,framMesDataObj.targetY,framMesDataObj.clearTag,gotoFrame,loop]);
						_frameMesDic[resultBitmapData] = [offX,offY,resultBitmapData.width,resultBitmapData.height
							,framMesDataObj.targetX,framMesDataObj.targetY,framMesDataObj.clearTag,gotoFrame,loop];
					}
				}
			}
			
			//测试代码
			//			var bitmap:Bitmap = new Bitmap(bitmapData);
			//			bitmap.scaleX = bitmap.scaleY = .5;
			//			bitmap.y = 100;
			//			App.appStage.addChild(bitmap);
			var endBitmapData:BitmapData = new BitmapData(totalContainer.width,totalContainer.height,true,0);
			endBitmapData.draw(totalContainer);
			returnObj["endBimapData"] = endBitmapData.clone();
			returnObj["frameMes"] = frameMes;
			return returnObj;
		}
		
		/**
		 * 1.两张位图宽高相等：如果两张位图像素相差范围超过总大小的60% 对比结果直接返回 第二张位图 否则 从第二张位图的对应位置上截取
		 * 	   对应位图区域返回
		 * 2.如果两张位图 宽高不等 直接返回第二张位图 
		 * 3.如果两张位图完全相等 返回第二张
		 * @param bitmapData 当前帧位图
		 * @param otherBitmapData 前一帧位图
		 * @return 
		 * 
		 */		
		private function compareBitmapData(bitmapData:BitmapData,otherBitmapData:BitmapData):FrameMesDataObj
		{
			var returnFrameMesDataObj:FrameMesDataObj = new FrameMesDataObj();
			if(bitmapData!=null && otherBitmapData!=null)
			{
				//两张位图宽高不等 直接返回第二张位图
				var compareResult:Object = bitmapData.compare(otherBitmapData);
				if(compareResult == -3 ||compareResult == -4 || compareResult == 0)
				{
					returnFrameMesDataObj.bitmapData = bitmapData;
					returnFrameMesDataObj.clearTag = 1;
				}else
				{
					if(compareResult is BitmapData)
					{
						var resultBitmapData:BitmapData =  BitmapData(compareResult);
						//用来对比的面积
						var compareArea:int = bitmapData.width*bitmapData.height;
						
						var resultRect:Rectangle = resultBitmapData.getColorBoundsRect(0xFFFFFF,0xFFFFFF,false);//resultBitmapData.width*resultBitmapData.height;
						var resultArea:int = resultRect.width*resultRect.height;
						// 如果不同区域面积 大于等于该帧位图面积的60% 则直接返回第二帧位图
						if(resultArea >= compareArea*.6)
						{
							returnFrameMesDataObj.bitmapData = bitmapData;
							returnFrameMesDataObj.clearTag = 1;
						}else
						{
							var endBitmapData:BitmapData = new BitmapData(resultRect.width,resultRect.height,true,0);
							endBitmapData.copyPixels(bitmapData,resultRect,new Point(0,0));
							returnFrameMesDataObj.clearTag = 0;
							returnFrameMesDataObj.targetX = resultRect.x;
							returnFrameMesDataObj.targetY = resultRect.y;
							returnFrameMesDataObj.bitmapData = endBitmapData;
						}
						
					}else
					{
						returnFrameMesDataObj.bitmapData = bitmapData;
						returnFrameMesDataObj.clearTag = 1;
					}
				}
			}
			
			return returnFrameMesDataObj;
		}
	}
}
/**
 * 序列位图帧辅助信息类 
 * @author jasonwluck
 * 
 */
import flash.display.BitmapData;

class FrameMesDataObj
{
	private var _targetX:Number = 0;
	private var _targetY:Number = 0;
	private var _clearTag:int;
	private var _bitmapData:BitmapData;
	
	public function get targetX():Number
	{
		return _targetX;
	}
	
	public function set targetX(value:Number):void
	{
		_targetX = value;
	}
	
	public function get targetY():Number
	{
		return _targetY;
	}
	
	public function set targetY(value:Number):void
	{
		_targetY = value;
	}
	
	/**
	 * 0为不需要清除上一帧位图  1为需要清除 
	 */	
	public function get clearTag():int
	{
		return _clearTag;
	}
	
	public function set clearTag(value:int):void
	{
		_clearTag = value;
	}
	
	public function get bitmapData():BitmapData
	{
		return _bitmapData;
	}
	
	public function set bitmapData(value:BitmapData):void
	{
		_bitmapData = value;
	}
}